package com.smartlib.cmnObject.ui;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.Scroller;

import com.smartlib.cmnObject.util.LogUtil;


/**
 * 自定义下拉刷新
 * Created by admin on 16/6/30.
 */
public class PullReflush extends ViewGroup {

    private Scroller mScroller;

    private int mDownX, mDownY;
    private float x, y;
    private int maxFlingVelocity, minFlingVelocity;
    private int orientation;
    private VelocityTracker velocityTracker;

    private int desireWidth, desireHeight;


    private int mPointerId;

    public PullReflush(Context context, AttributeSet attrs) {
        super(context, attrs);
        mScroller = new Scroller(context);

    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        int left = 0;
        int top = 0;
        int right = 0;
        int bottom = 0;
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            right = left + childView.getMeasuredWidth();
            bottom = top + childView.getMeasuredHeight();
            childView.layout(left, top, right, bottom);
        }
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        desireWidth = 0;
        desireHeight = 0;
        int count = getChildCount();
        for (int i = 0; i < count; ++i) {
            View v = getChildAt(i);
            if (v.getVisibility() != View.GONE) {
                measureChild(v, widthMeasureSpec,
                        heightMeasureSpec);
                desireWidth += v.getMeasuredWidth();
                desireHeight = Math.max(desireHeight, v.getMeasuredHeight());

            }

        }

        // count with padding
        desireWidth += getPaddingLeft() + getPaddingRight();
        desireHeight += getPaddingTop() + getPaddingBottom();

        // see if the size is big enough
        desireWidth = Math.max(desireWidth, getSuggestedMinimumWidth());
        desireHeight = Math.max(desireHeight, getSuggestedMinimumHeight());

        setMeasuredDimension(resolveSize(desireWidth, widthMeasureSpec),
                resolveSize(desireHeight, heightMeasureSpec));
        LogUtil.logI(desireHeight + "desireHeight");
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int action = event.getAction();
        //将事件加入到VelocityTracker中，用于计算手指抬起时的初速度
        if (velocityTracker == null) {
            velocityTracker = VelocityTracker.obtain();
        }
        velocityTracker.addMovement(event);
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mPointerId = event.getPointerId(0);
                x = event.getX();
                y = event.getY();
                if (!mScroller.isFinished())
                    mScroller.abortAnimation();
                break;
            case MotionEvent.ACTION_MOVE:
                // 获取当前手指id所对应的索引，虽然在ACTION_DOWN的时候，我们默认选取索引为0
                // 的手指，但当有第二个手指触摸，并且先前有效的手指up之后，我们会调整有效手指
                // 屏幕上可能有多个手指，我们需要保证使用的是同一个手指的移动轨迹，
                // 因此此处不能使用event.getActionIndex()来获得索引
                final int pointerIndex = event.findPointerIndex(mPointerId);
                float mx = event.getX(pointerIndex);
                float my = event.getY(pointerIndex);
                //此处的moveBy是根据水平或是垂直排放的方向，
                //来选择是水平移动还是垂直移动
                moveBy((int) (x - mx), (int) (y - my));
                x = mx;
                y = my;
                break;
            case MotionEvent.ACTION_UP:
                //maxFlingVelocity是通过ViewConfiguration来获取的初速度的上限
                //这个值可能会因为屏幕的不同而不同
                velocityTracker.computeCurrentVelocity(1000, ViewConfiguration.getMaximumFlingVelocity());
                float velocityX = velocityTracker.getXVelocity(mPointerId);
                float velocityY = velocityTracker.getYVelocity(mPointerId);

                //用来处理实际的移动
                completeMove(-velocityX, -velocityY);
                if (velocityTracker != null) {
                    velocityTracker.recycle();
                    velocityTracker = null;
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                // 获取离开屏幕的手指的索引
                int pointerIndexLeave = event.getActionIndex();
                int pointerIdLeave = event.getPointerId(pointerIndexLeave);
                if (mPointerId == pointerIdLeave) {
                    // 离开屏幕的正是目前的有效手指，此处需要重新调整，并且需要重置VelocityTracker
                    int reIndex = pointerIndexLeave == 0 ? 1 : 0;
                    mPointerId = event.getPointerId(reIndex);
                    // 调整触摸位置，防止出现跳动
                    x = event.getX(reIndex);
                    y = event.getY(reIndex);
                    if (velocityTracker != null)
                        velocityTracker.clear();
                }
                break;
            default:
                break;
        }
        return false;
    }


    public void moveBy(int deltaX, int deltaY) {
        if (Math.abs(deltaY) >= Math.abs(deltaX))
            scrollBy(0, deltaY);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return false;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return super.dispatchTouchEvent(ev);
    }

    private void completeMove(float velocityX, float velocityY) {
        int mScrollY = getScrollY();
        int maxY = desireHeight - getHeight();

        if (mScrollY > maxY) {
            // 超出了下边界，弹回
            mScroller.startScroll(0, mScrollY, 0, maxY - mScrollY);
            invalidate();
        } else if (mScrollY < 0) {
            // 超出了上边界，弹回
            mScroller.startScroll(0, mScrollY, 0, -mScrollY);
            invalidate();
        } else if (Math.abs(velocityY) >= minFlingVelocity && maxY > 0) {
            mScroller.fling(0, mScrollY, 0, (int) velocityY, 0, 0, 0, maxY);
            invalidate();
        }
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(0, mScroller.getCurrY());
            postInvalidate();
        }
    }

}
